if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
    message(FATAL_ERROR "LuisaCompute only supports 64-bit platforms")
endif ()

message(STATUS "Build for ${CMAKE_SYSTEM} (${CMAKE_SYSTEM_PROCESSOR})")

if (WIN32)
    find_file(LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH "SDKManifest.xml" HINTS "$ENV{WINDOWSSDKDIR}" NO_DEFAULT_PATH)
    if (LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH)
        file(STRINGS "${LUISA_COMPUTE_WINDOWS_SDK_MANIFEST_PATH}" LUISA_COMPUTE_WINDOWS_SDK_IDENTITY REGEX "PlatformIdentity")
        if (LUISA_COMPUTE_WINDOWS_SDK_IDENTITY)
            string(REGEX REPLACE "PlatformIdentity = \".*Version=([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)\"" "\\1" LUISA_COMPUTE_WINDOWS_SDK_VERSION "${LUISA_COMPUTE_WINDOWS_SDK_IDENTITY}")
            string(STRIP "${LUISA_COMPUTE_WINDOWS_SDK_VERSION}" LUISA_COMPUTE_WINDOWS_SDK_VERSION)
            if (LUISA_COMPUTE_WINDOWS_SDK_VERSION MATCHES "PlatformIdentity")
                set(LUISA_COMPUTE_WINDOWS_SDK_VERSION "")
            endif ()
        endif ()
        if (LUISA_COMPUTE_WINDOWS_SDK_VERSION)
            message(STATUS "Windows SDK found: ${LUISA_COMPUTE_WINDOWS_SDK_VERSION}")
        else ()
            message(WARNING "Windows SDK found but failed to parse the version. DirectX backend may not build correctly.")
        endif ()
    else ()
        message(WARNING "Windows SDK not found. DirectX backend may not build correctly.")
    endif ()
endif ()

if (LUISA_COMPUTE_BUILD_TESTS)
    if (NOT LUISA_COMPUTE_ENABLE_DSL)
        message(WARNING "DSL is required for tests. The DSL will be enabled.")
        set(LUISA_COMPUTE_ENABLE_DSL ON CACHE BOOL "Enable C++ DSL" FORCE)
    endif ()
endif ()

# check Rust support
if (NOT DEFINED CARGO_HOME)
    if ("$ENV{CARGO_HOME}" STREQUAL "")
        if (CMAKE_HOST_WIN32)
            set(CARGO_HOME "$ENV{USERPROFILE}/.cargo")
        else ()
            set(CARGO_HOME "$ENV{HOME}/.cargo")
        endif ()
    else ()
        set(CARGO_HOME "$ENV{CARGO_HOME}")
    endif ()
endif ()

if (NOT DEFINED LUISA_COMPUTE_ENABLE_RUST)
    set(LUISA_COMPUTE_ENABLE_RUST ON)
endif ()

if (LUISA_COMPUTE_ENABLE_RUST OR LUISA_COMPUTE_ENABLE_CPU OR LUISA_COMPUTE_ENABLE_REMOTE)
    find_program(CARGO_EXE cargo NO_CACHE HINTS "${CARGO_HOME}" PATH_SUFFIXES "bin")
    if (CARGO_EXE)
        set(LUISA_COMPUTE_ENABLE_RUST ON)
    else ()
        set(LUISA_COMPUTE_ENABLE_RUST OFF)
    endif ()
    if (LUISA_COMPUTE_ENABLE_RUST)
        message(STATUS "Enable Rust support (toolchain found at ${CARGO_EXE})")
    else ()
        message(WARNING "\nRust-dependent features are enabled but the Rust toolchain is not found on your system. \n\
    To install Rust, run `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` on unix environment\n\
    or download and run the installer from https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe on windows environment.\n")
    endif ()
endif ()

function(report_feature_not_available option_name feature_name)
    if (LUISA_COMPUTE_CHECK_BACKEND_DEPENDENCIES)
        message(WARNING "The ${feature_name} is not available. The ${feature_name} will be disabled.")
        set(LUISA_COMPUTE_ENABLE_${option_name} OFF CACHE BOOL "Enable ${feature_name}" FORCE)
    else ()
        message(FATAL_ERROR "The ${feature_name} is not available. Please install the dependencies to enable the ${feature_name}.")
    endif ()
endfunction()

if (LUISA_COMPUTE_ENABLE_DX)
    set(LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION "10.0.20348")
    if (NOT WIN32)
        report_feature_not_available(DX "DirectX backend")
    elseif (LUISA_COMPUTE_WINDOWS_SDK_VERSION)
        if (${LUISA_COMPUTE_WINDOWS_SDK_VERSION} VERSION_LESS ${LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION})
            message(WARNING "Expected Windows SDK >= ${LUISA_COMPUTE_EXPECTED_WINDOWS_SDK_VERSION} for DirectML support but you are using ${LUISA_COMPUTE_WINDOWS_SDK_VERSION}. The DirectX backend will be disabled. Please consider update the SDK with Visual Studio Installer.")
            report_feature_not_available(DX "DirectX backend")
        endif ()
    endif ()
endif ()

if (LUISA_COMPUTE_ENABLE_METAL)
    if (NOT APPLE OR NOT ${CMAKE_C_COMPILER_ID} MATCHES "Clang" OR NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
        report_feature_not_available(METAL "Metal backend")
    endif ()
endif ()

if (LUISA_COMPUTE_ENABLE_CUDA)
    find_package(CUDAToolkit 11.7 QUIET)
    if (NOT CUDAToolkit_FOUND)
        report_feature_not_available(CUDA "CUDA backend")
    endif ()
endif ()

if (LUISA_COMPUTE_ENABLE_VULKAN)
    find_package(Vulkan QUIET)
    if (NOT Vulkan_FOUND)
        report_feature_not_available(VULKAN "Vulkan backend")
    endif ()
endif ()

if (NOT LUISA_COMPUTE_ENABLE_RUST)
    if (LUISA_COMPUTE_ENABLE_CPU OR LUISA_COMPUTE_ENABLE_REMOTE)
        report_feature_not_available(CPU "CPU backend")
        report_feature_not_available(REMOTE "Remote backend")
    endif ()
endif ()

if (UNIX AND NOT APPLE AND LUISA_COMPUTE_ENABLE_WAYLAND)
    find_program(LUISA_COMPUTE_WAYLAND_SCANNER wayland-scanner)
    find_package(PkgConfig QUIET)
    if (PKG_CONFIG_FOUND)
        pkg_check_modules(Wayland QUIET wayland-client)
    endif ()
    if (NOT LUISA_COMPUTE_WAYLAND_SCANNER OR NOT Wayland_FOUND)
        report_feature_not_available(WAYLAND "Wayland support")
    endif ()
endif ()

if (SKBUILD OR LUISA_COMPUTE_FORCE_PYTHON_BINDINGS)
    find_package(Python3 COMPONENTS Interpreter Development.Module QUIET REQUIRED)
endif ()

if (LUISA_COMPUTE_ENABLE_GUI)
    # currently nothing to check
endif ()

if (LUISA_COMPUTE_ENABLE_CLANG_CXX)
    find_package(Clang CONFIG QUIET)
    if (NOT Clang_FOUND)
        report_feature_not_available(CLANG_CXX "Clang C++")
    endif ()
endif ()
